// mykit.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "crashdump.h"
#include "message.h"
#include "threadpool.h"
#include "matrix.h"

class MyHandler : public MessageHandler {
public:
	 void handleMessage(std::shared_ptr<Message> msg) override {
		msg->dump();

		switch (msg->what_) {
		case 0: stop(); break;
		}
	}
};

static void test_message()
{
	auto handler(std::make_shared<MyHandler>());
	handler->start();

	auto msg = Message::obtain();
	msg->what_ = 1;
	handler->sendMessage(msg);

	auto msg1 = Message::obtain();
	msg1->what_ = 0;
	handler->sendMessageDelay(msg1, 5000);

	auto msg2 = Message::obtain();
	msg2->what_ = 2;
	handler->sendMessageDelay(msg2, 1000);

#if 1
	for (int i = 3; i <= 100; i++) {
		auto msgTemp = Message::obtain();
		msgTemp->what_ = i;
		handler->sendMessageDelay(msgTemp, 1000 + i * 10);
	}
#endif

	handler->postDelayed([]() { MLOG_DEBUG("post delay"); }, 1500);
	handler->post([]() { MLOG_DEBUG("post delay"); });

	handler->join();
}

static void test_matrix()
{
	float data[] = { 1.1f, 2.2f, 3.3f, 4.4f };
	Matrix2Df m1(2, 2, data), m2(2, 2, data);

	if (m1 == m2) {
		std::cout << "m1 equals m2" << std::endl;
	}

	m1[3] = 5.5f;
	std::cout << m1 << std::endl;
	if (m1 != m2) {
		std::cout << "m1 not equals m2" << std::endl;
	}

	Matrix2Df m01 = m1 + m2;
	Matrix2Df m02 = m1 * m2;
	Matrix2Df m03 = m1 * 5;
	Matrix2Df m04 = 5 * m1;
	Matrix2Df m05 = m1 - m2;

	std::cout << m03 << std::endl;
	std::cout << m04 << std::endl;
	std::cout << m05 << std::endl;

	float data1[] = { 1, 0, 10, -1, 5, 2, 7, 1 };
	Matrix2Df m3(2, 4, data1);

	std::cout << m3 << std::endl;
	std::cout << m3.t() << std::endl;

	float res = 0;
	if (!m3.det(res)) {
		std::cout << "fail to calc |m3|" << std::endl;
	}

	float data2[] = { 6, 1,1,4,-2,5,2,8,7 };
	Matrix2Df m4(3, 3, data2);
	m4.det(res);
	std::cout << "|m4|=" << res << std::endl;


	float data3[] = { 1,-1,2 };
	float data4[] = { 2,-1,0, 1,1,3, 1,2,1 };
	Matrix2Df m5(1, 3, data3), m6(3, 3, data4);
	Matrix2Df m06 = m5 * m6;
	std::cout << m06 << std::endl;

	float data5[] = { 1,2,-1, 3,1,0, -1,-1,-2 };
	Matrix2Df m7(3, 3, data5);
	std::cout << m7.adj() << std::endl;

	float data6[] = { 1,2,3, 1,0,-1, 0,1,1 };
	Matrix2Df m8(3, 3, data6);
	std::cout << m8.inv() << std::endl;
	m8.tr(res);
	std::cout << res << std::endl;
}

static void test_threadpool()
{
	ThreadPool pool(4);
	std::vector< std::future<int> > results;

	for (int i = 0; i < 8; ++i) {
		results.emplace_back(pool.enqueue([i] {
				std::cout << "hello " << i << std::endl;
				std::this_thread::sleep_for(std::chrono::seconds(1));
				std::cout << "world " << i << std::endl;
				return i * i;
		}));
	}

	for (auto&& result : results)
		std::cout << result.get() << ' ';
	std::cout << std::endl;
}

static void test_crashdump()
{
	CrashDump dump;
	int* p = nullptr;
	*p = 5;
}

// valgrind --tool=memcheck --leak-check=full ./mykit
int main(int argc, char *argv[])
{
	// test_crashdump();
	test_message();
	// test_matrix();

	test_threadpool();

	MLOG_DEBUG("end of main");
	return 0;
}